package com.zyh.utils;

import com.zyh.anno.MyJsonFormat;
import com.zyh.anno.MyJsonIgnore;
import com.zyh.anno.MyJsonProperty;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author zyh
 * @Date 2024/8/15 11:45
 * @Description 技术：反射+注解+泛型
 */

public final class MyJsonUtils {
    private MyJsonUtils() {
    }

    //1.将一个java普通对象转为Json字符串(泛型)
    public static <T> String domainToJsonString(T t) {
        try {
            //1.数据校验
            if (t == null) {
                return "{}";
            }
            if (t instanceof Map) {
                throw new IllegalArgumentException("参数不能传双列集合");
            }
            //创建一个sb对象
            StringBuilder sb = new StringBuilder();
            sb.append("{");
            //拿到对象的字节码文件
            Class c = t.getClass();
            //拿到所有的属性
            Field[] declaredFields = c.getDeclaredFields();
            //遍历集合拿到每个属性
            for (Field declaredField : declaredFields) {
                //打开访问开关
                declaredField.setAccessible(true);
                //拿到每个属性的名字
                String fieldName = declaredField.getName();
                //拿到每个属性的值
                Object fieldVale = declaredField.get(t);
                //过滤掉 serialVersionUID
                if ("serialVersionUID".equals(fieldName)) {
                    continue;
                }
                //判断属性是由有注解
                if (declaredField.isAnnotationPresent(MyJsonIgnore.class)) {
                    //跳过拼接
                    continue;
                }
                if (declaredField.isAnnotationPresent(MyJsonProperty.class)) {
                    //拿到 MyJsonProperty 注解对象
                    MyJsonProperty annotation = declaredField.getAnnotation(MyJsonProperty.class);
                    //拿到 MyJsonProperty 注解对象的值并赋值给fieldName
                    fieldName = annotation.value();
                }
                if (declaredField.isAnnotationPresent(MyJsonFormat.class)) {
                    //拿到 MyJsonFormat 注解对象
                    MyJsonFormat annotation = declaredField.getAnnotation(MyJsonFormat.class);
                    //拿到 MyJsonFormat 注解对象的值
                    fieldVale = new SimpleDateFormat(annotation.pattern()).format(fieldVale);
                }
                //对属性名字进行改装
                fieldName = "\"" + fieldName + "\"";
                //对属性值进行判断
                if (fieldVale instanceof String || fieldVale instanceof StringBuffer || fieldVale instanceof StringBuilder || fieldVale instanceof Date) {
                    fieldVale = "\"" + fieldVale + "\"";
                }
                //循环拼接
                sb.append(fieldName + ":" + fieldVale + ",");
            }
            //删除最后一个逗号
            sb.deleteCharAt(sb.length() - 1);
            //拼接一个}
            sb.append("}");
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //2.将一个java集合对象转为Json字符串(泛型)
    public static <T> String collectionToJsonString(Collection<T> coll) {
        //校验coll
        if (coll == null || coll.size() == 0) {
            return "[]";
        }
        //创建一个sb
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (T t : coll) {
            String s = domainToJsonString(t);
            //循环拼接
            sb.append(s + ",");
        }
        //删除最后一个逗号
        sb.deleteCharAt(sb.length() - 1);
        sb.append("]");
        return sb.toString();
    }

    //3.将一个java对象转为Json字符串(泛型)
    public static <T> String objectTOJsonString(T t) {
        //校验t
        if (t instanceof Map) {
            throw new IllegalArgumentException("不能传入双列集合");
        }
        if (t == null) {
            return "{}";
        }
        if (t instanceof Collection) {
            return collectionToJsonString(((Collection<?>) t));
        }
        return domainToJsonString(t);
    }

    //4.将一个Json字符串转为java普通对象
    //"{"bName":"西游记","price":19.9,"createTime":"2024-08-15"}"
    public static <T> T jsonStringToDomain(String str, Class<T> tClass) {
        try {
            //校验str
            if (str == null || str.length() == 0 || str.isEmpty() || "".equals(str)) {
                return null;
            }
            //校验tClass
            if (tClass == null) {
                throw new IllegalArgumentException("字节码对象为空");
            }
            //拿到tClass空对象
            T t = tClass.getDeclaredConstructor().newInstance();
            //去掉str左右两边的{}
            str = str.substring(1);
            str = str.substring(0, str.length() - 1);
            //按照逗号切割
            String[] split = str.split(",");
            //遍历数组拿到每个key和value的元素
            for (String keyValue : split) {//["bName":"西游记","price":19.9]
                //按照冒号切割
                String[] item = keyValue.split(":");
                for (int i = 0; i < item.length; i++) {//["bName","西游记"]
                    //第一个作为属性名，第二个作为属性值
                    String fieldName = item[0].replaceAll("\"", "").trim();
                    String fieldValue = item[1].replaceAll("\"", "").trim();
                    Field field = tClass.getDeclaredField(fieldName);//拿到字节码对象的模板的属性
                    field.setAccessible(true);
                    //获取属性对应的属性值
                    Object value = field.get(t);
                    //判断属性值类型
                    if (field.getType().getName().contains("Integer")) {
                        value = Integer.parseInt(fieldValue);
                        field.set(t, value);
                    } else if (field.getType().getName().contains("Double")) {
                        value = Double.parseDouble(fieldValue);
                        field.set(t, value);
                    } else if (field.getType().getName().contains("Date")) {//日期格式转换
                        Date date = new Date(Long.parseLong(fieldValue));
                        field.set(t, date);
                    } else {
                        field.set(t, fieldValue);
                    }
                }
            }
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //5.将一个Json字符串转为java集合对象
    //[{"author":"zyh","createTime":1723713118009,"name":"西游记","price":19.9},{"author":"zyh1","createTime":1723713118009,"name":"红楼梦","price":29.9}]
    public static <T> Collection<T> jsonStringToCollection(String str, Class<T> tClass) {
        //校验str和tClass
        if (str == null || str.length() == 0 || "".equals(str)) {
            return null;
        }
        if (tClass == null) {
            throw new IllegalArgumentException("字节码对象不能为空");
        }
        //去掉左右两边的[]
        str = str.replaceAll("\\[|\\]", "");
        //按照},{切割
        String[] split = str.split("},\\{");
        //第一个最后边补}，最后一个最前面补{，中间的前面补{，后面补}
        split[0] = split[0] + "}";
        split[split.length - 1] = "{" + split[split.length - 1];
        for (int i = 1; i < split.length - 1; i++) {
            split[i] = "{" + split[i] + "}";
        }
        //创建一个集合
        Collection<T> list = new ArrayList<>();
        //遍历split拿到每一个元素
        for (String item : split) {//{"author":"zyh","createTime":1723713118009,"name":"西游记","price":19.9}
            //调用 jsonStringToDomain() 方法
            T t = jsonStringToDomain(item, tClass);
            list.add(t);
        }
        return list;
    }
}
